﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration.Provider;
using System.Web.Security;
namespace CVTH.Provider
{
    public class MembershipProvider : SqlMembershipProvider
    {
        private int autoUnlockTimeout = 60;  //Default to 60 minutes

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            string sunlockTimeOut = config["autoUnlockTimeout"];
            if (!String.IsNullOrEmpty(sunlockTimeOut))
                autoUnlockTimeout = Int32.Parse(sunlockTimeOut);
            config.Remove("autoUnlockTimeout");

            base.Initialize(name, config);
        }

        private bool AutoUnlockUser(string username)
        {
            MembershipUser mu = this.GetUser(username, false);
            if ((mu != null) && (mu.IsLockedOut) && (mu.LastLockoutDate.ToUniversalTime().AddMinutes(autoUnlockTimeout) < DateTime.UtcNow))
            {
                bool retval = mu.UnlockUser();
                if (retval)
                    return true;
                else
                    return false; //something went wrong with the unlock
            }
            else
                return false; //not locked out in the first place
            //or still locked out
        }

        public override bool ValidateUser(string username, string password)
        {
            bool retval = base.ValidateUser(username, password);

            //The account may be locked out at this point
            if (retval == false)
            {
                bool successfulUnlock = AutoUnlockUser(username);
                if (successfulUnlock)
                    //re-attempt the login
                    return base.ValidateUser(username, password);
                else
                    return false;
            }
            else
                return retval;  //first login was successful
        }

        public override bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            bool retval = base.ChangePassword(username, oldPassword, newPassword);
            ChangPassWordOldNew(username, oldPassword, newPassword);

            //The account may be locked out at this point
            if (retval == false)
            {
                bool successfulUnlock = AutoUnlockUser(username);
                if (successfulUnlock)
                    //re-attempt the password change
                    return base.ChangePassword(username, oldPassword, newPassword);
                else
                    return false;
            }
            else
                return retval;  //first change was successful
        }

        private void ChangPassWordOldNew(string username, string oldPassword, string newPassword)
        {
            
        }

        public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
        {
            bool retval = base.ChangePasswordQuestionAndAnswer(username, password, newPasswordQuestion, newPasswordAnswer);

            //The account may be locked out at this point
            if (retval == false)
            {
                bool successfulUnlock = AutoUnlockUser(username);
                if (successfulUnlock)
                    //re-attempt the password change
                    return base.ChangePasswordQuestionAndAnswer(username, password, newPasswordQuestion, newPasswordAnswer);
                else
                    return false;
            }
            else
                return retval;  //first change was successful
        }

        public override string ResetPassword(string username, string passwordAnswer)
        {
            //A MembershipPasswordException could be due to a lockout
            try
            {
                return base.ResetPassword(username, passwordAnswer);
            }
            catch { }

            bool successfulUnlock = AutoUnlockUser(username);
            if (successfulUnlock)
                //re-attempt the password reset
                return base.ResetPassword(username, passwordAnswer);
            else
                throw new ProviderException("The attempt to auto unlock the user failed during ResetPassword.");
        }

        public override string GetPassword(string username, string passwordAnswer)
        {
            //A MembershipPasswordException could be due to a lockout
            try
            {
                return base.GetPassword(username, passwordAnswer);
            }
            catch (MembershipPasswordException me) { }

            bool successfulUnlock = AutoUnlockUser(username);
            if (successfulUnlock)
                //re-attempt the password retrieval
                return base.GetPassword(username, passwordAnswer);
            else
                throw new ProviderException("The attempt to auto unlock the user failed during GetPassword.");
        }
    }
}
